﻿using JoeyLibs.IdleStartMenu.IUI;
using JoeyLibs.IdleStartMenu.IViewModel;
using JoeyLibs.IdleStartMenu.Model;
using JoeyLibs.IdleStartMenu.UIUtility;
using JoeyLibs.Utility;
using Microsoft.Practices.Unity;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace JoeyLibs.IdleStartMenu.WPFUI
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window, IMenuUI
    {
        const double WIDTH_INIT = 380;
        const double WIDTH_SETTING = 380;
        const double WIDTH_EDIT = 480;

        List<Process> openedProcesses;

        private IMainViewModel viewModel;

        private List<Button> processButtons;

        private FormHandleState formState;

        public MainWindow()
        {
            InitializeComponent();

            openedProcesses = new List<Process>();
            
            IUnityContainer container = ContainerHelper.Container;
            this.viewModel = container.Resolve<IMainViewModel>();

            this.cbxMultiProcess.Checked += cbxMultiProcess_ChangeChecked;
            this.cbxMultiProcess.Unchecked += cbxMultiProcess_ChangeChecked;     
        }

        #region Event
        void cbxMultiProcess_ChangeChecked(object sender, RoutedEventArgs e)
        {
            SetMultiProcessOpened();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            CreateAdvert();

            RefreshData();
        }

        private void btnSetting_Click(object sender, RoutedEventArgs e)
        {
            string saveText = "保 存";
            if (saveText.Equals(btnSetting.Content))
            {
                if (SaveSetting())
                {
                    HiddenSetting();
                    RefreshData();
                }
            }
            else
            {
                this.btnSetting.Content = saveText;
                ShowSetting();
            }            
        }

        private void btnCancleSetting_Click(object sender, RoutedEventArgs e)
        {
            ResetSetting();
            HiddenSetting();
            RefreshData();
        }

        private void item_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            CreateRightClickMenu(sender as Control);
        }

        private void btnSaveEdit_Click(object sender, RoutedEventArgs e)
        {
            ProcessModel model = borderEdit.DataContext as ProcessModel;
            if (model == null)
            {
                return;
            }

            //this.formState = FormHandleState.Edit;
            if (this.formState == FormHandleState.Add)
            {
                model.HandleState = ModelHandleState.Add;
                this.viewModel.ProcessModels.Add(model);
            }
            else
            {
                model.HandleState = ModelHandleState.Edit;
            }

            borderEdit.Visibility = System.Windows.Visibility.Hidden;
        }

        #region 顶部菜单事件
        private void MenuBackup_Click(object sender, RoutedEventArgs e)
        {
            OpenFileDialog ofd = UICommon.OpenBackupFileDialog(UICommon.RandomFileName);
            ofd.Title = LanguageResource.Title_Backup;
            ofd.CheckFileExists = false;
            if (ofd.ShowDialog() == true)
            {
                viewModel.ExportSetting(ofd.FileName);
            }
        }

        private void MenuRestore_Click(object sender, RoutedEventArgs e)
        {
            if (MsgBox.Show(LanguageResource.Msg_BeSureRestore, buttons : MessageBoxButton.OKCancel) 
                == MessageBoxResult.OK)
            {
                OpenFileDialog ofd = UICommon.OpenBackupFileDialog();
                ofd.Title = LanguageResource.Title_Backup;
                ofd.CheckFileExists = true;
                if (ofd.ShowDialog() == true)
                {
                    viewModel.ImportSetting(ofd.FileName);
                    HiddenSetting();
                    RefreshData();
                }
            }
        }

        private void MenuToInit_Click(object sender, RoutedEventArgs e)
        {
            if (MsgBox.Show(LanguageResource.Msg_BeSureResetInit, buttons: MessageBoxButton.OKCancel)
                == MessageBoxResult.OK)
            {
                viewModel.ResetInit();
                HiddenSetting();
                RefreshData();
            }
        }

        private void MenuExit_Click(object sender, RoutedEventArgs e)
        {
            this.Close(); 
        }

        private void MenuHelp_Click(object sender, RoutedEventArgs e)
        {
            Process p = UICommon.StartProcess("iexplore.exe", "http://freedong.cnblogs.com/");
        }

        private void MenuAbout_Click(object sender, RoutedEventArgs e)
        {
            Process p = UICommon.StartProcess("iexplore.exe", "http://freedong.cnblogs.com/");
        }
        #endregion
        #endregion

        #region Show & Hidden
        string addButtonName = "btn";
        bool IsShowSetting = false;
        /// <summary>
        /// 显示设置
        /// </summary>
        private void ShowSetting()
        {
            IsShowSetting = true;
            btnCancleSetting.Visibility = Visibility.Visible;
            lblMsgEdit.Visibility = Visibility.Visible;
            AddGridMenuRow();

            foreach (var item in this.processButtons)
            {
                item.MoveRow(1);
                item.AllowDrop = true;   
                item.MouseRightButtonUp += item_MouseRightButtonUp;             
            }

            CreateAddButton();
        }

        /// <summary>
        /// 隐藏设置
        /// </summary>
        private void HiddenSetting()
        {
            if (!IsShowSetting)
            {
                return;
            }

            lblMsgEdit.Visibility = Visibility.Hidden;
            btnCancleSetting.Visibility = Visibility.Hidden; 
            this.btnSetting.Content = "设 置";
            this.Width = WIDTH_INIT;
            gridMenu.RowDefinitions.TryRemoveAt(0);
            gridMenu.Children.Remove(gridMenu.Children.FirstOrDefault<UIElement>(
                p => (p as Control).Name == addButtonName));

            this.processButtons.ForEach(
                p =>
                {
                    p.MouseRightButtonUp -= item_MouseRightButtonUp;
                    p.ContextMenu = null;
                    p.MoveRow(-1);
                });

            SetAllClickStyle(false);
            HiddenEdit();
            IsShowSetting = false;
        }

        private void ShowEdit(object data = null, bool isEdit = false)
        {
            this.borderEdit.Visibility = Visibility.Visible;
            this.Width = WIDTH_EDIT;
            this.formState = isEdit ? FormHandleState.Edit : FormHandleState.Add;
            this.borderEdit.DataContext = data;
            this.txtName.Focus();
        }

        private void HiddenEdit()
        {
            this.borderEdit.Visibility = Visibility.Hidden;
            this.Width = WIDTH_SETTING;
            this.formState = FormHandleState.Default;
        }

        /// <summary>
        /// 重置设置
        /// </summary>
        private void ResetSetting()
        {
            UICommon.ClearTextBox(txtArguments, txtName, txtProcessPath);
        }

        private void SetAllClickStyle(bool set = true, Button btnNotSet = null)
        {
            this.gridMenu.Children.Foreach<UIElement>(p => UICommon.SetButtonClickStyle(p as Button, set));
            if (btnNotSet != null)
            {
                UICommon.SetButtonClickStyle(btnNotSet, !set);
            }
        }

        private void AddGridMenuRow()
        {
            gridMenu.AddRow(60);
        }

        #endregion

        #region Handle Data
        /// <summary>
        /// 保存设置
        /// </summary>
        private bool SaveSetting()
        {
            this.viewModel.Update();
            return true;
        }

        private void AddProcess(int orderNum)
        {
            if (orderNum <= 0)
            {
                return;
            }

            ProcessModel tempAdd = new ProcessModel();
            tempAdd.OrderNum = -1;
            this.viewModel.UpdateOrder(tempAdd, orderNum);

            ShowEdit(tempAdd);
        }

        public void DeleteProcess(ProcessModel model, Control control)
        {
            model.HandleState = ModelHandleState.Delete;
            gridMenu.Children.Remove(control);
            int rowIndex = control.GetRow();
            gridMenu.RowDefinitions.Remove(gridMenu.RowDefinitions[rowIndex]);
            this.processButtons.Where(p => p.GetRow() > rowIndex)
                .Foreach<Button>(p => p.MoveRow(-1));
        }

        private void RefreshData()
        {
            gridMenu.Children.Clear();
            gridMenu.RowDefinitions.Clear();

            SetMultiProcessOpened();
            CreateProcessControls();
        }
        #endregion

        #region 创建按钮

        private Button CreateButton(ProcessModel model)
        {
            Button btn = CreateProcessButton();
            btn.Content = model.Name;
            btn.ToolTip = string.IsNullOrEmpty(model.Arguments) ? model.ProcessPath : model.Arguments;
            btn.Tag = model;

            btn.Click += (sender, e) => {
                this.viewModel.CreateProcess(model);
            };
            return btn;
        }

        private void CreateAddButton()
        {
            Button btn = CreateProcessButton();
            btn.Click += (sender, e) =>
            {
                ProcessModel addModel = new ProcessModel();
                addModel.OrderNum = int.MaxValue;
                ShowEdit(addModel);
                SetAllClickStyle(false, btn);
            };

            btn.Name = addButtonName;
            btn.Content = "增 加";
            btn.ToolTip = "点击以增加一个进程";
            btn.SetColumn(1).SetRow(0);
            gridMenu.Children.Add(btn);
        }

        private Button CreateProcessButton()
        {
            return UICommon.CreateWP8Button(50, 100);
        }
        #endregion

        #region 创建右键菜单
        /// <summary>
        /// 创建右键菜单
        /// </summary>
        private void CreateRightClickMenu(Control control)
        {
            control.ContextMenu = null;
            ProcessModel model = control.Tag as ProcessModel;

            CreateRightClickMenu("修改", control, (cSender, ce) =>
            {
                ShowEdit(control.Tag, true);
            });

            CreateRightClickMenu("删除", control, (cSender, ce) =>
            {
                if (MsgBox.Show(string.Format(LanguageResource.Msg_ConfirmDelete_Format, model.Name),
                    buttons: MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    DeleteProcess(model, control);
                }
            });

            CreateRightClickMenu("上移", control, (cSender, ce) =>
            {
                MoveButton(control, control.GetRow() - 1);
            });

            CreateRightClickMenu("下移", control, (cSender, ce) =>
            {
                MoveButton(control, control.GetRow() + 1);
            });

            CreateRightClickMenu("移到顶部", control, (cSender, ce) =>
            {
                MoveButton(control, this.processButtons.Min(p => p.GetRow()));
            });

            CreateRightClickMenu("移到底部", control, (cSender, ce) =>
            {
                MoveButton(control, this.processButtons.Max(p => p.GetRow()));
            });

            CreateRightClickMenu("在下方新增", control, (cSender, ce) =>
            {
                ProcessModel tempModel = control.Tag as ProcessModel;
                if (tempModel == null)
                {
                    return;
                }

                AddProcess(tempModel.OrderNum + 1);
            });
        }

        /// <summary>
        /// 创建右键菜单
        /// </summary>
        private void CreateRightClickMenu(string name, Control control, RoutedEventHandler handle)
        {
            if (control.ContextMenu == null)
            {
                control.ContextMenu = new ContextMenu();
            }

            SetAllClickStyle(false, control as Button);
            MenuItem mi1 = new MenuItem();
            mi1.Header = name;
            mi1.Click += handle;
            control.ContextMenu.Items.Add(mi1);
        }

        #endregion

        #region 移动
        private void MoveButton(Control control, int newIndex)
        {
            ProcessModel tempModel = control.Tag as ProcessModel;
            if (tempModel == null)
            {
                return;
            }

            int oldIndex = control.GetRow();
            this.viewModel.UpdateOrder(tempModel, tempModel.OrderNum - 1);

            if (newIndex > oldIndex)
            {
                this.processButtons.Where(p => p.GetRow() <= newIndex && p.GetRow() > oldIndex)
                   .Foreach<Button>(p => p.MoveRow(-1));
            }
            else
            {
                this.processButtons.Where(p => p.GetRow() >= newIndex && p.GetRow() < oldIndex)
                    .Foreach<Button>(p => p.MoveRow(1));
            }

            control.SetRow(newIndex);
        }
        #endregion

        #region IMenuUI 成员

        public void SetMultiProcessOpened()
        { 
            this.viewModel.IsMultiProcessOpened = this.cbxMultiProcess.IsChecked.HasValue ? 
                this.cbxMultiProcess.IsChecked.Value : false; 
        }

        public IMainViewModel ViewModel
        {
            get { return this.viewModel; }
        }

        public void CreateProcessControls()
        {
            this.processButtons = new List<Button>();
            Button btn = null;
            int index = 0;
            foreach (ProcessModel item in this.viewModel.ProcessModels)
            {
                if (item.HandleState == ModelHandleState.Delete)
                {
                    continue;
                }

                AddGridMenuRow();

                btn = CreateButton(item);
                btn.SetRow(index++);
                this.gridMenu.Children.Add(btn);
                this.processButtons.Add(btn);
            }
        }

        public void CreateAdvert()
        {
            if (AppConfig.Instance.IsShowAdvert)
            {
                var task = this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    this.wbAdvert.NavigateToString(AppConfig.Instance.AdvertBottom);       
                }));

                task.Completed += (sender, e) => {
                    this.wbAdvert.Visibility = System.Windows.Visibility.Visible;
                };
            }
        }
        #endregion
    }
}